﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Brc_PaaS.Api.Common;
using Brc_PaaS.Api.Filters;
using Brc_PaaS.Common.Model.Basic;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
using Exceptionless;
using Microsoft.AspNetCore.Diagnostics;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Http;
using System.Text;
using Com.Ctrip.Framework.Apollo;

namespace Brc_PaaS.Api
{
    /// <summary>
    /// 启动类
    /// </summary>
    public class Startup
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="configuration">配置服务</param>
        /// <param name="env">环境服务</param>
        public Startup(IConfiguration configuration, IHostingEnvironment env)
        {

            Configuration = configuration;
            var builder = new ConfigurationBuilder()
               .SetBasePath(env.ContentRootPath)
               .AddJsonFile("./appsettings.json", optional: false, reloadOnChange: true)
               .AddJsonFile($"./appsettings.{env.EnvironmentName}.json", optional: true)

               .AddEnvironmentVariables();
            Configuration = builder.Build();
            builder.AddApollo(Configuration.GetSection("Apollo"))
                   .AddDefault()
                   .AddNamespace(Configuration["Apollo:Namespace"]);
            Configuration = builder.Build();

        }

        /// <summary>
        /// 配置服务接口
        /// </summary>
        public IConfiguration Configuration { get; }
        private List<LocalService> localServices;
        /// <summary>
        /// 容器接口
        /// </summary>
        public IContainer Container;

        /// <summary>
        /// 配置服务
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options =>
            {
                options.Filters.Add(typeof(GlobalExceptionFilter));
                options.Filters.Add(typeof(GlobalFilter));       


            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddControllersAsServices();


            //禁用core下面的默认行文，自定义模型验证
            services.Configure<ApiBehaviorOptions>(options =>
            {
                options.InvalidModelStateResponseFactory = (context) =>
                {
                    BaseResponseModel response = new BaseResponseModel();
                    StringBuilder stringBuilder = new StringBuilder();
                    int i = 1;
                    foreach (var item in context.ModelState)
                    {
                        if (item.Value.Errors.Any())
                        {
                            string error = item.Value.Errors.FirstOrDefault()?.ErrorMessage;
                            error = (error.Contains("Unexpected", StringComparison.OrdinalIgnoreCase)) ? "Json格式不正确" : error;
                            stringBuilder.Append($" {i}:{error} |");
                            i++;
                        }
                    }
                    response.IsSuccess = false;
                    response.Msg = stringBuilder.ToString().Substring(0, stringBuilder.Length - 1).Trim();
                    return new JsonResult(response);
                };
            });
            //注册Swagger生成器，定义一个和多个Swagger 文档
            localServices = JsonConvert.DeserializeObject<List<LocalService>> (Configuration.GetValue<string>("LocalService"));
            //注册 Swagger
            services.AddSwaggerGen(sg =>
            {
                if (localServices != null && localServices.Any())
                {
                    localServices.ForEach(i =>
                    {
                        sg.SwaggerDoc(i.Title, new Microsoft.OpenApi.Models.OpenApiInfo
                        {
                            Title = i.Title,
                            Version = i.Version,
                            Description = i.Description
                        });
                    });
                }


                if (File.Exists(XmlCommentsFilePath))
                {
                    sg.IncludeXmlComments(XmlCommentsFilePath, true);
                }
            });
            //添加cors 服务 配置跨域处理             
            services.AddCors(options =>
            {
                options.AddPolicy("any", builder =>
                {
                    builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .AllowCredentials();//指定处理cookie
                });
            });
            services.AddHostedService<PaaSRabbitMqListener>();
            return RegisterAutofac(services, Configuration);//注册Autofac            
        }
        private static string XmlCommentsFilePath
        {
            get
            {
                var basePath = PlatformServices.Default.Application.ApplicationBasePath;
                var fileName = $"{System.Reflection.Assembly.GetEntryAssembly().GetName().Name}.xml";
                return Path.Combine(basePath, fileName);
            }
        }
        private IServiceProvider RegisterAutofac(IServiceCollection services, IConfiguration Configuration)
        {
            //实例化Autofac容器
            var builder = new ContainerBuilder();
            builder.Populate(services);
            builder.RegisterModule(new AutofacModule(Configuration));
            var container = builder.Build();
            //第三方IOC接管 core内置DI容器 
            return new AutofacServiceProvider(container);
        }

        /// <summary>
        /// 管道配置
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {

            if (env.IsDevelopment())
            {
                app.UseExceptionHandler("/Error");
            }          
            else
            {
                app.UseExceptionHandler("/Error");
            }
            app.UseHsts();
            app.UseSwagger(c =>
            {
                c.RouteTemplate = "{documentName}/swagger.json";
            }).
            UseSwaggerUI(s =>
            {
                if (localServices != null && localServices.Any())
                {
                    localServices.ForEach(i =>
                    {
                        s.SwaggerEndpoint($"/{i.EndPoint}/swagger.json", i.Title);
                        s.RoutePrefix = string.Empty;
                    });
                }

            });

            //使用Exceptionless
            ExceptionlessClient.Default.Configuration.ApiKey = Configuration.GetSection("Exceptionless:ApiKey").Value;
            ExceptionlessClient.Default.Configuration.ServerUrl = Configuration.GetSection("Exceptionless:ServerAddress").Value;
            app.UseExceptionless();


            app.UseCors("any");
            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}
